home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / util / misc / cy1_0.lha / cy
Encoding:
Text File  |  1995-03-15  |  15.7 KB  |  659 lines

  1. /*
  2.  * cy    Copyright © 1995 by Rick Younie
  3.  *        Freely Distributable.
  4.  *        Do not distribute your changes please.
  5.  *
  6.  * $VER: Rick Younie  10 March 1995
  7.  *        rick@freenet.vancouver.bc.ca (quicker)
  8.  *        rick@emma.panam.wimsey.com (may be more reliable)
  9.  *
  10.  * USAGE: '?' for usage
  11.  *
  12.  * SYNOPSIS: 
  13.  *    - Cybercron management program
  14.  *
  15.  */
  16.     signal on BREAK_C
  17.     signal on HALT
  18.  
  19. /*    -------------------------------------------------------------------
  20.  *    constants and assigns
  21.  */
  22.     /* set these for your system */
  23.  
  24.     screenwidth        = 640
  25.     screenheight    = 200
  26.     editor            = 'C:ed -sticky'    /* editor must hang on to CLI */
  27.     CyberCron        = 'CyberCron'        /* path+name of CC program */
  28.     crontab            = 'SYS:s/CronTab'
  29.     sendmail        = '"sendmail -f %s -R *"%s*""'
  30.     logfile            = 't:CyberCron.log'
  31.  
  32.     /* end settings */
  33.  
  34.  
  35.     lf                = '0a'x
  36.     cr                = '0d'x
  37.     crlf            = cr || lf
  38.     csi                = '9b'x
  39.     rows            = screenheight % 8 - 2
  40.     cols            = screenwidth % 8 - 1
  41.     startcmd        = CyberCron 'CRONTAB' crontab,
  42.                                 'SENDMAIL' sendmail
  43.  
  44. /*    -------------------------------------------------------------------
  45.  *
  46.  */
  47. Main:
  48.     address 'CYBERCRON'
  49.     options results
  50.     options failat 99
  51.     arg option
  52.  
  53.     select
  54.         when option = '-N' then call NextEvent
  55.         when option = '-L' then call ListEvents
  56.  
  57.         when option = '-E' then call Edit
  58.  
  59.         when option = '-B' then call StartCyber
  60.         when option = '-Q' | option = '-K' then call KillCyber
  61.  
  62.         when option = '-S'
  63.             then if Suspend_Resume('SUSPEND') then say ShowStatus()
  64.         when option = '-R'
  65.             then if Suspend_Resume('RESUME') then say ShowStatus()
  66.  
  67.         when option = '' then call RawStuff
  68.  
  69.         otherwise Call Usage
  70.     end
  71.     exit 0
  72.  
  73. /*####################################################################
  74.   ##                         raw window                             ##
  75.   ####################################################################*/
  76.  
  77. /*  -----------------------------------------------------------------*/
  78.  
  79. RawStuff:
  80.  
  81.     cursorUp        = '41'x
  82.     cursorDown        = '42'x
  83.     cursorRight        = '43'x
  84.     cursorLeft        = '44'x
  85.  
  86.     if ~Running()
  87.         then call ErX "..CyberCron not running - '?' for Usage"
  88.  
  89.     call MakeRaw
  90.  
  91. Refresh:
  92.     call WriteSkel            /* write header,footer */
  93.  
  94. ReScan:
  95.     numevents = ReadEvents()        /* get all queued events from CC */
  96.  
  97.     if numevents = 0    then page = 0
  98.                         else page = 1
  99.     row                = 1
  100.  
  101.     itemsPerPage    = rows - 8
  102.     itemsLastPage    = numevents // itemsPerPage
  103.     maxpage            = numevents % itemsPerPage + (itemsLastPage~=0)
  104.  
  105.     items.            = itemsPerPage
  106.     items.0            = 1
  107.     if itemsLastPage = 0    then items.maxpage = itemsPerPage
  108.                             else items.maxpage = itemsLastPage
  109.  
  110.     if numevents~=0 then call WritePage
  111.     else call WriteSkel
  112.  
  113.     /* we spend most of our time here, handling keystrokes
  114.      *
  115.      */
  116.     do forever
  117.  
  118.         oldpos = row
  119.         char = readch('STDIN', 1)
  120.  
  121.         select
  122.  
  123.             /* handle cursor keys */
  124.             when char = '9b'x then do
  125.                 char = readch('STDIN', 1)
  126.                 select
  127.                     when numevents=0 then nop
  128.                     when char = cursorDown then do
  129.                         row = row + 1
  130.                         if row > items.page then row = 1
  131.                         call MoveCursor
  132.                     end
  133.                     when char = cursorUp then do
  134.                         row = row - 1
  135.                         if row = 0 then row = items.page
  136.                         call MoveCursor
  137.                     end
  138.                     when char = cursorRight then do
  139.                         if page ~= maxpage then do
  140.                             page = page + 1
  141.                             call WritePage
  142.                         end
  143.                     end
  144.                     when char = cursorLeft then do
  145.                         if page > 1 then do
  146.                             page = page - 1
  147.                             call WritePage
  148.                         end    
  149.                     end
  150.                     otherwise nop
  151.                 end
  152.  
  153.             end        /* cursor keys */
  154.  
  155.             /* not a cursor key */
  156.             otherwise do
  157.                 select
  158.                     when char = 's'
  159.                         then if Suspend_Resume('SUSPEND') then call WriteStatus
  160.                     when char = 'r'
  161.                         then if Suspend_Resume('RESUME') then call WriteStatus
  162.                     when char = 'a' then call AddEvent('NORM')
  163.                     when char = 'A' then call AddEvent('CC')
  164.                     when char = 'e' then call EditCrontab
  165.                     when char = 'n' then signal Refresh /* ReScan? */
  166.                     when char = 'q' then do
  167.                         call CLineMsg '..really quit? Y/n '
  168.                         char = readch('STDIN',1)
  169.                         if upper(char)~='N' then leave
  170.                         call MsgAndDelay '..quit aborted'
  171.                     end
  172.                     when char = 'g' then call ToggleLogFile
  173.  
  174.                     /* dont allow the following options if no events */
  175.                     when numevents = 0 then nop
  176.  
  177.                     when char = 't' then do
  178.                         tmp = (page-1)*itemsPerPage + row
  179.                         tag.tmp = (tag.tmp=0)    /* toggle flag */
  180.                         if tag.tmp    then star = '*'
  181.                                     else star = ' '
  182.                         call writech 'STDOUT',csi || row+2';3H'star
  183.                         row = row + 1
  184.                         if row > items.page then row = 1
  185.                         call MoveCursor
  186.                     end
  187.  
  188.                     /*    space bar follows Tin behavior
  189.                      *        >1 page?
  190.                      *            - if ~last page, go to next
  191.                      *            - else if not at end of page, go to end
  192.                      *                    - else go to first page
  193.                      *        =1 page; if not at bottom, go there
  194.                      *                    else go to top
  195.                      */
  196.                     when char = ' ' then do
  197.                         if maxpage > 1 then do
  198.                             if page ~= maxpage then do
  199.                                 page = page + 1
  200.                                 call WritePage
  201.                             end
  202.                             else do
  203.                                 if row ~= items.page then do
  204.                                     row = items.page
  205.                                     call MoveCursor
  206.                                 end
  207.                                 else do
  208.                                     page = 1
  209.                                     call WritePage
  210.                                 end
  211.                             end
  212.                         end
  213.                         else do    /* only 1 page; go to bot/top */
  214.                             if row = items.page then row = 1
  215.                                                 else row = items.page
  216.                             call MoveCursor
  217.                         end
  218.                     end
  219.  
  220.                     when char = 'd' then call DeleteEvent
  221.                     when char = 'p' then call PurgeRexx
  222.                     otherwise nop
  223.                 end
  224.             end
  225.  
  226.         end /* select */
  227.  
  228.         call PrintTime
  229.  
  230.     end    /* forever */
  231.  
  232.     exit 0
  233.  
  234. MoveCursor:
  235.     call writech 'STDOUT', csi || oldpos+2';1H  '
  236.     call writech 'STDOUT', csi ||    row+2';1H->' || csi || rows';1H'
  237.     return
  238.     
  239. CLineMsg:
  240.     call writech 'STDOUT', csi || rows';1H'csi'K   'arg(1) || cr
  241.     return
  242.  
  243. /*  -------------------------------------------------------------------
  244.  *    
  245.  */
  246. WriteSkel:
  247.     prompt.1        = '[s]uspend [r]esume  [t]ag [d]elete  [e]dit_crontab resca[n]  lo[g]_file'
  248.     prompt.2        = '<=prev page  (spacebar)  next page=>  [aA]dd  [q]uit  [p]urge_rexx_events'
  249.  
  250.     'VERSION'
  251.     title    = 'CyberCron' word(result,1)
  252.  
  253.     call writech 'STDOUT', csi'H'csi'J' || center(title,cols) || crlf
  254.     call writech 'STDOUT', csi || rows - 4';1H'center(prompt.1,cols)
  255.     call writech 'STDOUT', csi || rows - 3';1H'center(prompt.2,cols)
  256.  
  257. WriteStatus:
  258.     call writech 'STDOUT', csi || rows - 2';1H'center(ShowStatus(),cols)
  259.     call CLineMsg ''
  260.  
  261. PrintTime:
  262.     call writech 'STDOUT', csi || '1;4H'time()'  'date('E') || csi || rows';1H'
  263.     return
  264.  
  265. /*  ------------------------------------------------------------------- */
  266. WritePage:
  267.  
  268.     tmp = right('p'page 'of' maxpage,10)
  269.     call writech 'STDOUT', csi || '1;'cols-length(tmp)'H'tmp
  270.  
  271.     offset = (page-1)*itemsPerPage    /* offset into event.i */
  272.  
  273.     /* write this pages events to window */
  274.     do i = 1 to items.page
  275.         tmp = offset + i
  276.         if tag.tmp    then star = '*'
  277.                     else star = ' '
  278.         call writech 'STDOUT', csi || i+2';1H'csi'K  'star || event.tmp || crlf
  279.     end i
  280.  
  281.     /* clear leftover lines */
  282.     do i = items.page+1 to itemsPerPage + 1
  283.         call writech 'STDOUT', csi || i+2';1H'csi'K'
  284.     end i
  285.  
  286.     /* reset to first entry whenever page is redrawn */
  287.     row = 1
  288.     call writech 'STDOUT', csi || row+2';1H->'
  289.  
  290. WipeBottom2:
  291.     /* wipe 2 command lines, positions cursor at bottom */
  292.     call writech 'STDOUT', csi || rows-1';1H'csi'J'csi || rows';1H'
  293.     return
  294.  
  295. /*  ----------------------------------------------------------------
  296.  *    ssc_id.i = 12345678'ext' 12345678 0x12345678    for the sort
  297.  *        - ext=ext+1 for every CC event read so :OBEYQUEUE-type
  298.  *            events dont get mixed up by the sort
  299.  *        - shifted to just 'ssc id' after the sort
  300.  *    event.i = time date event_to_execute
  301.  */
  302. ReadEvents:
  303.  
  304.     tag.        = 0            /* clear tags on a new read */
  305.  
  306.     /* get all events in CC-id format */
  307.     'LIST_EVENTS'
  308.     list = result
  309.  
  310.     if left(list,2)~='0x' then ssc_id.0 = 0    /* no events queued */
  311.  
  312.     else do
  313.         if option = '' then call CLineMsg '..getting events'
  314.         /* fill 'sssc.ext sssc 0x' array for sort */
  315.         ssc_id.0 = words(list)
  316.         do i = 1 to ssc_id.0
  317.             /* get time for its next execution */
  318.             id = word(list,i)
  319.             'EVENT_NEXT_EXEC' id
  320.             ssc =  result
  321.             if ssc = '' then tmp = 0         /* could not be found */
  322.             tmp = ssc || right('0'i,2)    /* 01,02..added to events
  323.                             so QUEUE events of same time dont scramble */
  324.             ssc_id.i = tmp ssc id
  325.         end i
  326.  
  327.         if option = '' then call CLineMsg '..sorting'
  328.  
  329.         /* one of Knuth's sort algorithms
  330.             - rony@wu-wien.ac.at (Rony G. Flatscher) */
  331.         m = 1
  332.         do while (9 * m + 4) < ssc_id.0
  333.             m = m * 3 + 1
  334.         end
  335.     
  336.         do while m > 0
  337.             k = ssc_id.0 - M
  338.             do j = 1 to k
  339.                 q = j
  340.                 do while q > 0
  341.                     l = q + m
  342.                     if ssc_id.q <= ssc_id.l then leave
  343.                     /* switch elements */
  344.                     tmp        = ssc_id.q
  345.                     ssc_id.q = ssc_id.l
  346.                     ssc_id.l = tmp
  347.                     q = q - m
  348.                 end
  349.             end
  350.             m = m % 3
  351.         end        /* sort */
  352.  
  353.         if option = '' then call CLineMsg '..converting'
  354.  
  355.         /* now fill event.i with events sorted as to time */
  356.         today = date('E')
  357.         scnwidth = cols - 4
  358.         do i = 1 to ssc_id.0
  359.  
  360.             parse var ssc_id.i . ssc id
  361.             /* lose the ssc+extension variable to save a little confusion */
  362.             ssc_id.i = ssc id
  363.  
  364.             'SHOW_EVENT' id
  365.             event.i = subword(result,7)        /* the event */
  366.  
  367.             'EXPAND_SSSC' ssc
  368.             parse var result . min hr day mon yr .
  369.             date = right('00'day,2)'/'right('00'mon,2)'/'right(yr,2)
  370.             if date = today then date = '        '
  371.  
  372.             /* truncate for screen */
  373.             event.i = right('00'hr,2)':'right('00'min,2) date event.i
  374.             if length(event.i) > scnwidth then event.i = left(event.i,scnwidth)
  375.         end i
  376.  
  377.     end
  378.  
  379.     return ssc_id.0
  380.  
  381. /*  -------------------------------------------------------------------
  382.  *
  383.  */
  384. PurgeRexx:
  385.     'PURGE_REXX_EVENTS'        /* no RC? */
  386.     call MsgAndDelay '..rexx events purged'
  387.     signal ReScan
  388.  
  389. /*  -------------------------------------------------------------------
  390.  *
  391.  */
  392. ToggleLogFile:
  393.  
  394.     if right(ShowStatus(),2) = 'ON' then 'CLOSE_LOG_FILE'
  395.     else 'NEW_LOG_FILE' logfile
  396.  
  397.     if RC ~= 0 then call MsgAndDelay '..error toggling' logfile
  398.  
  399.     signal WriteStatus
  400.  
  401.     return
  402.  
  403. /*  -------------------------------------------------------------------
  404.  *
  405.  */
  406. EditCrontab:
  407.     call CLineMsg '..editing' crontab
  408.     if Edit()~=0 then do
  409.         call delay 3*50
  410.         signal Refresh    /* dos can mess up window with err msg */
  411.     end
  412.     signal ReScan
  413.  
  414. Edit:
  415.     address 'COMMAND' editor crontab
  416.     return RC
  417.  
  418. /*  -------------------------------------------------------------------
  419.  *    NORM    = hh:mm event
  420.  *    CC        = min hour day month dow(Sun=0) event
  421.  */
  422. AddEvent:
  423.     parse arg type
  424.  
  425.     prompt.NORM    = 'hh:mm'
  426.     prompt.CC    = 'min hr day mon dow(Sun=0)'
  427.     prompt = csi || rows-1';1H'csi'K'prompt.type' event'csi || rows';1H'
  428.  
  429.     do forever
  430.         call writech 'STDOUT',prompt
  431.         string = GetEvent()
  432.         if string = '' then do
  433.             call MsgAndDelay '..aborting - no add'
  434.             signal WipeBottom2
  435.         end
  436.         if type = 'NORM' then do
  437.             parse var string hr ':' min event
  438.             event = strip(event)
  439.             string = min hr '* * *' event
  440.         end
  441.  
  442.         'ADD_EVENT' string
  443.         
  444.         /* event was added ok - go get new lineup from CC */
  445.         if RC=0 then do
  446.             call MsgAndDelay 'ok'
  447.             signal ReScan
  448.         end
  449.  
  450.         else do            /* not added - try again */
  451.             call writech 'STDOUT', csi || rows-1';33H **error** [ <ret> to continue ]'
  452.             call readch 'STDIN', 1
  453.             call writech 'STDOUT', csi || rows-1';1H'csi'J'csi || rows
  454.         end
  455.  
  456.     end
  457.     return
  458.  
  459. /*  ----------------handle user add_event input---------------------- */
  460. GetEvent:
  461.     string = ''
  462.  
  463.     do forever
  464.         char = readch('STDIN',1)
  465.         select
  466.             when char>'1f'x & char < '7f'x then do
  467.                 if length(string) <= cols-2 then string = string || char
  468.                 else char = '07'x
  469.                 call writech 'STDOUT',char
  470.             end
  471.  
  472.             /* delete a character */
  473.             when char = '08'x then do
  474.                 if string ~== '' then do
  475.                     string = substr(string,1,length(string)-1)
  476.                     call writech 'STDOUT', csi'D'csi'P'
  477.                 end
  478.             end
  479.  
  480.             /* done */
  481.             when char = cr then break
  482.  
  483.             /* discard cursor key 2nd byte */
  484.             when char = csi then call readch 'STDIN',1
  485.             otherwise nop
  486.         end
  487.     end
  488.     return string
  489.  
  490. /*  -------------------------------------------------------------------
  491.  *    Delete all tagged events; else current event
  492.  */
  493. DeleteEvent:
  494.  
  495.     /* any tagged for delete? */
  496.     tagged = 0
  497.     do i = 1 to numevents
  498.         tagged = tagged + tag.i
  499.     end i
  500.  
  501.     /* got tagged event(s) */
  502.     if tagged > 0 then do
  503.         call CLineMsg 'delete' tagged 'tagged event'copies('s',tagged~=1)'? Y/n '
  504.         char = readch('STDIN',1)
  505.         if upper(char)='N' then break
  506.         do i = 1 to numevents
  507.             if tag.i then call DeleteOne word(ssc_id.i,2)
  508.         end
  509.         signal ReScan
  510.     end
  511.  
  512.     /* delete current event? */
  513.     call CLineMsg 'delete this event? Y/n '
  514.     char = readch('STDIN',1)
  515.     if upper(char)='N' then call MsgAndDelay '..aborting - no delete'
  516.     else do
  517.         tmp = (page-1)*itemsPerPage+row
  518.         call DeleteOne word(ssc_id.tmp,2)
  519.         signal ReScan
  520.     end
  521.     return
  522.  
  523. DeleteOne:
  524.     parse arg id
  525.     call CLineMsg '..deleting'
  526.     'DELETE_EVENT' id
  527.     if RC~=0 then call MsgAndDelay '..couldn''t find event'
  528.     return    
  529.  
  530. /* ------ write a message to command line, wait, then wipe it ----- */
  531. MsgAndDelay:
  532.     parse arg msg
  533.     call CLineMsg msg
  534.     call delay 25
  535.     call CLineMsg ''
  536.     return    
  537.  
  538. /*####################################################################
  539.   ##                  do command line requests                      ##
  540.   ####################################################################*/
  541.  
  542. /*  -----------------------------------------------------------------*/
  543. ListEvents:
  544.     if ~Running() then say '..CyberCron isn''t running'
  545.     else do
  546.         'LIST_EVENTS'
  547.         list = result
  548.         if left(list,2)~='0x' then say '..no events queued'
  549.         else do i = 1 to words(list)
  550.             'SHOW_EVENT' word(list,i)
  551.             say subword(result,2)
  552.         end
  553.         say '  'ShowStatus()
  554.     end
  555.     return
  556.  
  557. /*  -----------------------------------------------------------------*/
  558. NextEvent:
  559.     if ~Running() then say '..CyberCron isn''t running'
  560.     else do
  561.         numevents = ReadEvents()
  562.         if numevents = 0 then say '..no events queued'
  563.         else do
  564.             lasttime = word(ssc_id.1,1)    /* show all events queued for next time */
  565.             do i = 1 to numevents
  566.                 thistime = word(ssc_id.i,1)
  567.                 if thistime ~= lasttime then break
  568.                 id = word(ssc_id.i,2)
  569.                 say event.i
  570.                 lasttime = thistime
  571.             end i
  572.             say '  'ShowStatus()
  573.         end
  574.     end
  575.     return
  576.  
  577. /*  -------------------------------------------------------------  */
  578. Suspend_Resume:
  579.     running = Running()
  580.     if ~running then say '..CyberCron isn''t running'
  581.     else ''arg(1)''
  582.     return running
  583.  
  584. /*  -------------------------------------------------------------  */
  585. ShowStatus:    PROCEDURE
  586.     'SHOW_STATUS'
  587.     parse var result activity ' "' ctab '" "' lfile '"'
  588.     star = copies('*',activity='SUSPENDED')
  589.     if lfile = '<None>' then tmp = 'OFF'
  590.     else tmp = 'ON'
  591.     return 'Status:'star||activity||star 'Crontab='ctab 'Log='tmp
  592.  
  593. /*  -------------------------------------------------------------  */
  594. KillCyber:
  595.     if ~Running() then say '..CyberCron isn''t running'
  596.     else do
  597.         'QUIT'
  598.         do i = 1 to 10
  599.             call delay 25
  600.             if ~Running() then break
  601.         end i
  602.  
  603.         if i <= 10 then say '..CyberCron is dead'
  604.         else say '..CyberCron will quit after the current job is finished'
  605.     end
  606.     return
  607.  
  608. /*  -------------------------------------------------------------  */
  609. StartCyber:
  610.     if Running() then say '..CyberCron is already running'
  611.     else do
  612.         address 'COMMAND' 'run >NIL: <NIL:' startcmd
  613.  
  614.         do i = 1 to 10
  615.             call delay 25
  616.             if Running() then break
  617.         end i
  618.  
  619.         if i <= 10 then say '..CyberCron started'
  620.         else say '..couldn''t start' CyberCron
  621.     end
  622.     return
  623.  
  624. /*  ------ 0=not running; 1=running ------------------------------  */
  625. Running:
  626.     return show('PORT','CYBERCRON')
  627.  
  628. /* ---------------------------------------------------------------- */
  629. MakeRaw:
  630.     call close 'STDOUT'
  631.     call close 'STDIN'
  632.     call open 'STDOUT','RAW:0/0/'screenwidth'/'screenheight'//NOSIZE'
  633.     call pragma '*','STDOUT'
  634.     call open 'STDIN','*'
  635.     return
  636.  
  637. /* ----------------------------------------------------------------  */
  638. Usage:
  639.     say 'Usage: cy -option'
  640.     say '    -e  edit crontab ['editor crontab']'
  641.     say '    -b  begin CyberCron ['CyberCron']'
  642.     say '    -q  quit (kill) CyberCron'
  643.     say '    -s  suspend'
  644.     say '    -r  resume'
  645.     say '    -n  next event(s) to execute'
  646.     say '    -l  list all events'
  647.     say '        no option is the most fun'
  648.     say '   editor  =' editor
  649.     say '   logfile =' logfile
  650.     say '   crontab =' crontab
  651.     exit 0
  652.  
  653. ErX:
  654.     say arg(1)
  655.  
  656. HALT:
  657. BREAK_C:
  658.     exit 10
  659.